package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * 自动填充公共字段切面类
 * @author zgp
 * @version V1.0
 * @date 2025-01-14 10:34
 */
@Aspect
@Slf4j
@Component
public class AutoFillAspect {

    @Pointcut("@annotation(com.sky.annotation.AutoFill)")
    public void pt(){}

    @Before("pt()")
    public void autoFillBeforeAdvice(JoinPoint joinPoint){
        log.info("切面注入公共属性字段值...");
        // 当前时间
        LocalDateTime now = LocalDateTime.now();
        // 操作用户ID
        Long empId = BaseContext.getCurrentId();

        try {
            // 1. 通过反射获取@AutoFill注解对象
            MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
            Method method = methodSignature.getMethod();
            AutoFill autoFill = method.getAnnotation(AutoFill.class);
            if(Objects.isNull(autoFill)){
                return;
            }
            // 2. 获取方法参数对象
            Object[] args = joinPoint.getArgs();
            if(Objects.isNull(args) || args.length == 0){
                return;
            }
            Object pojo = args[0];
            // 获取参数的Class对象，通过反射为其设置值
            Class<?> clazz = pojo.getClass();
            // 3. 获取注解属性，判断是新增还是修改操作
            OperationType value = autoFill.value();
            if(OperationType.INSERT == value){
                // 通过方法名和方法参数类型，获取get/set方法
                Method setCreateTimeMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUserMethod = clazz.getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTimeMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUserMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 反射调用set方法设置值
                setCreateTimeMethod.invoke(pojo, now);
                setCreateUserMethod.invoke(pojo, empId);
                setUpdateTimeMethod.invoke(pojo, now);
                setUpdateUserMethod.invoke(pojo, empId);
            }else if (OperationType.UPDATE == value){
                // 通过方法名和方法参数类型，获取get/set方法
                Method setUpdateTimeMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUserMethod = clazz.getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                // 反射调用set方法设置值
                setUpdateTimeMethod.invoke(pojo, now);
                setUpdateUserMethod.invoke(pojo, empId);
            }
        } catch (Exception e) {
            log.error("error message：{}", e.getMessage(), e);
        }
    }
}
